package yf.mall.utils.app;

import yf.mall.enums.app.AppTimeTypeEnum;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * @author yxmds  时间相关处理类
 */
public final class AppDateUtil {

    private AppDateUtil() {
    }

    public static LocalDateTime groupOrderByTime(Integer timeType, Date time) {
        if (timeType == null) {
            return time.toInstant().atZone(ZoneId.systemDefault()).toLocalDate().atStartOfDay();
        }
        AppTimeTypeEnum timeTypeEnum = AppTimeTypeEnum.getByKey(timeType);

        switch (timeTypeEnum) {
            case MIN_30:
                return roundToNearest30Minutes(time);
            case HOUR_1:
                return roundToNearest1Hours(time);
            case HOUR_2:
                return roundToNearest2Hours(time);
        }
        return java.time.LocalDateTime.from(time.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
    }

    // 将时间戳舍入到最接近的30分钟的时间段
    public static LocalDateTime roundToNearest30Minutes(Date date) {
        LocalDateTime dateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        int minute = dateTime.getMinute();
        int minuteOfHour = minute % 30;
        return dateTime.minusMinutes(minuteOfHour).minusSeconds(dateTime.getSecond());
    }

    // 将时间戳舍入到最接近的1小时的时间段
    public static LocalDateTime roundToNearest1Hours(Date date) {
        LocalDateTime dateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        int minute = dateTime.getMinute();
        int minuteOfHour = minute % 60;
        return dateTime.minusMinutes(minuteOfHour).minusSeconds(dateTime.getSecond());
    }

    // 将时间戳舍入到最接近的2小时的时间段
    public static LocalDateTime roundToNearest2Hours(Date date) {
        LocalDateTime dateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        // 舍入到最接近的2小时
        long roundedHours = (dateTime.getHour() / 2) * 2;
        return dateTime.truncatedTo(ChronoUnit.HOURS).withHour((int) roundedHours);
    }

    public static List<LocalDateTime> generateTimeListByType(Integer timeType, Date begin, Date end) {
        if (begin == null || end == null) {
            return Collections.emptyList();
        }
        LocalDateTime beginTime = begin.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endTime = end.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        if (timeType == null) {
            return generateDateList(beginTime, endTime);
        }
        AppTimeTypeEnum timeTypeEnum = AppTimeTypeEnum.getByKey(timeType);
        switch (timeTypeEnum) {
            case MIN_30:
                return generateMinTimeList(beginTime, endTime, 30);
            case HOUR_1:
                return generateHourlyTimeList(beginTime, endTime);
            case HOUR_2:
                return generateTwoHourlyTimeList(beginTime, endTime);
        }
        return generateDateList(beginTime, endTime);
    }

    /**
     * @param startTime
     * @param endTime
     * @param intervalMinutes
     * @return
     */
    public static List<LocalDateTime> generateMinTimeList(LocalDateTime startTime, LocalDateTime endTime, int intervalMinutes) {
        List<LocalDateTime> timeList = new ArrayList<>();

        LocalDateTime current = startTime;
        while (current.isBefore(endTime)) {
            // 获取分钟部分
            int minutes = current.getMinute();

            // 如果分钟是0或30，添加到列表中
            if (minutes == 0 || minutes == 30) {
                timeList.add(current);
            }

            // 增加指定的分钟间隔
            current = current.plusMinutes(intervalMinutes);
        }

        return timeList;
    }

    public static List<LocalDateTime> generateHourlyTimeList(LocalDateTime startTime, LocalDateTime endTime) {
        List<LocalDateTime> timeList = new ArrayList<>();

        LocalDateTime current = startTime;
        while (current.isBefore(endTime)) {
            timeList.add(current);
            current = current.plus(1, ChronoUnit.HOURS);
        }

        return timeList;
    }

    public static List<LocalDateTime> generateTwoHourlyTimeList(LocalDateTime startTime, LocalDateTime endTime) {
        List<LocalDateTime> timeList = new ArrayList<>();

        LocalDateTime current = startTime;
        while (current.isBefore(endTime)) {
            timeList.add(current);
            current = current.plus(2, ChronoUnit.HOURS);
        }

        return timeList;
    }

    /**
     * @param startTime
     * @param endTime
     * @return
     */
    public static List<LocalDateTime> generateDateList(LocalDateTime startTime, LocalDateTime endTime) {
        List<LocalDateTime> dateList = new ArrayList<>();

        LocalDateTime current = startTime;
        while (current.isBefore(endTime)) {
            dateList.add(current);
            current = current.plus(1, ChronoUnit.DAYS);
        }

        return dateList;
    }
}
